﻿using BusinessService.Plugin;
using BusinessService.Plugin.Const;
using BusinessService.Plugin.Entity;
using BusinessService.Plugin.Helper;
using BusinessService.Plugin.ProtocolMethod;
using IFM.Core;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog.Configuration;
using SqlSugar;
using SqlSugar.Extensions;
using SqlSugarRepository;

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.DirectoryServices;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using TcpClient = TouchSocket.Sockets.TcpClient;

using MQTTnet.Client;
using MQTTnet.Server;
using server.Models;
using BusinessService.Plugin.DataSource.Sqlite.Dtos;
using BusinessService.Plugin.DataSource.Sqlite;
using TouchSocket.Sockets;
using System.Diagnostics;
using BusinessService.Plugin.Services.Dtos;


namespace BusinessService.Plugin.Services
{
    public class BackService
    {
        #region 结构函数注入
        private readonly TransferDtos _businessDto;
        private readonly SqlSugarRepository<ParameterSettings> _repParam;
        private readonly SqlSugarRepository<FilterTable> _repFilter;
        private readonly SqlSugarRepository<SelectFields> _repSelect;
        private readonly SqlSugarRepository<JsonBuildEntity> _repBuild;
        private readonly SqlSugarRepository<ProtocolClass> _repProtocol;
        private readonly SqlSugarRepository<AllSet> _repAllSet;

        public BackService(TransferDtos business
            , SqlSugarRepository<ParameterSettings> repParam
            , SqlSugarRepository<FilterTable> repFilter
            , SqlSugarRepository<SelectFields> repSelect
            , SqlSugarRepository<JsonBuildEntity> repBuild
            , SqlSugarRepository<ProtocolClass> repProtocol
            , SqlSugarRepository<AllSet> repAllSet
            )
        {
            _businessDto = business;

            _repParam = repParam;
            _repFilter = repFilter;
            _repSelect = repSelect;
            _repBuild = repBuild;
            _repProtocol = repProtocol;
            _repAllSet = repAllSet;
        }
        #endregion
        #region 跨线程更新控件
        /// <summary>
        /// 获取服务ID(使用Fody数据自动通知机制)
        /// </summary>
        /// <returns></returns>
        public async void GetServiceID()
        {
            SynchronizationContext? uiContext = SynchronizationContext.Current;//获取UI线程
            await Task.Run(async () =>
            {
                while (true)
                {
                    // 在另一个线程中  
                    uiContext?.Post(o =>
                    {
                        // 这里是UI线程  
                        //_businessDto.ID = $"后台线程随机发送测试：{Random.Shared.Next(1, 99999000).ToString()}   {uiContext.ToString()}";
                        //_businessDto.MyTable = _repDay
                        //.Where(x => x.V_Day.Equals(DateTime.Now.ToString("yyyy-MM-dd"))).ToPageList(1, 100);
                    }, null);
                    await Task.Delay(1000);
                }
            });
        }
        #endregion

        /// <summary>
        /// 执行数据运算,并向指定接口发送数据
        /// </summary>
        /// <returns></returns>
        public async Task PostDataAsync()
        {
            try
            {
                try
                {
                    Stopwatch sw = new Stopwatch();//程序耗时计算
                    sw.Start();

                    var builds = _repBuild.AsQueryable().ToList();
                    var FilterList = await _repFilter.AsQueryable().ToListAsync();///条件筛选表
                    var SelectList = await _repSelect.AsQueryable().ToListAsync();//选择字段表
                    var DataBases = await _repParam.AsQueryable()// 【主参数表】 查询所有与数据库查询有关的数据
                                                   .Where(x => x.V_ProtocolType.Equals("DataBase"))
                                                   .ToListAsync();///数据源表 

                    //循环遍历消息发送规则
                    builds.ForEach(async item =>
                    {
                        #region  消息查询->消息构造->消息生成


                        var DataSourceList = item.DataSourceList.ToObject<List<string>>();//数据源集合生成数据
                        var DBlist = DataBases.Where(x => DataSourceList.Contains(x.Name.Trim())).ToList();//获取与数据库设置名称相等的项
                        Dictionary<string, object> DBresult = new Dictionary<string, object>();
                        Dictionary<string, object> result = new Dictionary<string, object>();
                        if (DBlist.Count > 0)
                        {   //获取数据库的目标数据
                            DBresult = await GetDB(DBlist, FilterList, SelectList);
                        }

                        //需要发送的消息进行Json构造
                        result = await GetKeyValuePairs(DataSourceList);//获取除了数据库查询的其他数据源的数据
                        if (DBresult != null)
                        {
                            result = result.Concat(DBresult).ToDictionary(K => K.Key, V => V.Value);//数据连接
                        }
                        var msg = result.ToJsonString();//数据json化

                        #endregion
                        #region   Http/Socket/MQTT  转发消息模块
                        //Http协议转发处理
                        if (item.UploadTargetType.Equals("Http"))
                        {
                            var HttpInfo = _repAllSet.AsQueryable()
                                 .Where(x => x.N_Role.Equals(2))
                                .Where(x => x.V_Name.Equals(item.UploadTarget))
                                .Select(x => new
                                {
                                    x.Http_Method,
                                    x.Http_Token,
                                    x.Http_Url,
                                    x.Http_PostInfo
                                })
                                .First();
                            if (HttpInfo.Http_Method.Equals("Get"))
                                await ProtocolClass.HttpGetAsync(HttpInfo.Http_Url, HttpInfo.Http_Token);

                            if (HttpInfo.Http_Method.Equals("Post"))
                                await ProtocolClass.HttpPostAsync(HttpInfo.Http_Url, HttpInfo.Http_Token, HttpInfo.Http_PostInfo);
                        }
                        //获取对应的数据连接上下文

                        if (ProtocolClass.SendContexts.Count > 0)
                        {
                            var Context = ProtocolClass.SendContexts
                                 .Where(x => x.Name.Equals(item.UploadTarget))
                                 .FirstOrDefault();
                            if (!SqlFunc.IsNullOrEmpty(Context))
                            {
                                switch (Context.Type) //选择发送方式
                                {
                                    case "TCP": ProtocolClass.SocketSend(Context.Context, msg); break;
                                    case "MQTT":
                                        var topic = _repAllSet.AsQueryable()
                                          .Where(x => x.N_Role.Equals(2) && item.UploadTarget.Equals(x.V_Name))//获取所有的数据源信息
                                          .Select(x => x.MQTT_Topics)
                                          .First();
                                        ProtocolClass.Publish(Context.Context, topic, msg);
                                        break;
                                    //后续仿照此步骤添加。。。。。。。。

                                    default: break;
                                }
                            }
                        }
                        #endregion
                        //数据日志
                        sw.Stop();
                        _businessDto.RealTimeMessage = $"时间：{DateTime.Now}\r\n" +
                        $"消息：{msg}\r\n" +
                        $"发送耗时：{sw.ElapsedMilliseconds}ms.\r\n\r\n{_businessDto.RealTimeMessage}";
                        _businessDto.SendCount += 1;
                        if (_businessDto.RealTimeMessage.Length > 60000)
                        {
                            _businessDto.RealTimeMessage = string.Empty;
                        }
                    });
                }
                catch (Exception ex)
                {
                    _businessDto.ErrorCount += 1;
                    _businessDto.RealTimeMessage += $"时间{DateTime.Now}\r\n错误日志：{ex.Message}\r\n\r\n";
                    Log.Info($"时间{DateTime.Now}\r\n错误日志：{ex.Message}\r\n\r\n");
                }

            }
            catch (Exception e)
            {
                throw;
            }



        }

        /// <summary>
        /// 获取数据源信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Dictionary<string, object>> GetKeyValuePairs(List<string> input)
        {
            try
            {
                Dictionary<string, object> dict = new Dictionary<string, dynamic>();
                AllSetQueryInput param = new AllSetQueryInput();

                var list = await _repAllSet.AsQueryable()
                                   .InnerJoin<ParameterSettings>((a, p) => a.V_Name == p.Link)
                                      .Where((a, p) => a.N_Role.Equals(1) && input.Contains(p.Name))//获取所有的数据源信息
                                      .Select((a, p) => new
                                      {
                                          p.Name,
                                          a.V_ProtocolType,
                                          a.IP,
                                          a.Port,
                                          a.MQTT_Topics,
                                          a.Http_Url,
                                          a.Http_Method,
                                          a.Http_Token,
                                          a.Http_PostInfo,

                                      })
                                      .ToListAsync();
                //执行查表操作
                list.ForEach(async item =>
                     {
                         dynamic info = null;
                         switch (item.V_ProtocolType)
                         {

                             case "Socket":
                                 info = CacheManager.Default.Get<string>($"{item.IP}:{item.Port}"); break;
                             //后续仿照此步骤添加。。。。。。。。
                             case "MQTT":
                                 info = CacheManager.Default.Get<string>(item.MQTT_Topics); break;

                             case "Http":
                                 if (item.Http_Method.Equals("Get"))
                                     info = await ProtocolClass.HttpGetAsync(item.Http_Url, item.Http_Token);

                                 if (item.Http_Method.Equals("Post"))
                                     info = await ProtocolClass.HttpPostAsync(item.Http_Url, item.Http_Token, item.Http_PostInfo);
                                 break;

                             default:
                                 break;
                         }
                         dict.Add(item.Name, info);
                     });



                return dict;

            }
            catch (Exception ex)
            {
                _businessDto.RealTimeMessage += $"时间{DateTime.Now}\r\n错误日志：{ex.Message}\r\n\r\n";
                return new Dictionary<string, object>();
            }
        }


        /// <summary>
        /// 数据库获取数据(方法模块)
        /// </summary>
        /// <param name="mainList">数据源设置主表</param>
        /// <param name="FilterList">条件筛选表</param>
        /// <param name="SelectList">选择字段表</param>
        /// <returns></returns>
        public async Task<Dictionary<string, object>> GetDB(List<ParameterSettings> mainList, List<FilterTable> FilterList, List<SelectFields> SelectList)
        {
            try
            {
                Dictionary<string, object> dict = new Dictionary<string, dynamic>();
                mainList.ForEach(item =>
                {
                    try
                    {
                        #region 构造Where条件查询    
                        var Filter = FilterList.FindAll(x => x.P_Id.Equals(item.ID));
                        //构造Where条件查询                               
                        var conModels = new List<IConditionalModel>();
                        Filter.ForEach(f =>
                        {
                            string time = string.Empty;
                            if (DateTimeEnum.timeFormat.Contains(f.TargetValue))
                            {
                                //            "当前时间",
                                //"年(yyyy)",
                                //"月(yyyy-MM)",
                                //"日(yyyy-MM-dd)"

                                switch (f.TargetValue)
                                {
                                    case "日(yyyy-MM-dd)":
                                        time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day).ToString("yyyy-MM-dd");
                                        break;

                                    case "月(yyyy-MM)":
                                        time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day).ToString("yyyy-MM");
                                        break;

                                    case "年(yyyy)":
                                        time = DateTime.Now.Year.ToString();
                                        break;
                                    case "当前时间":
                                        time = DateTime.Now.ToString();
                                        break;
                                }
                            }
                            conModels.Add(new ConditionalModel
                            {
                                FieldName = f.SelectItem,
                                ConditionalType = Match.JudgeChanged(f.CompareAction),
                                FieldValue = time.Equals(string.Empty) ? f.TargetValue : time,
                                CSharpTypeName = f.CSharpTypeName
                            });
                        });

                        #endregion
                        #region 构造Select选择查询
                        var Select = SelectList.FindAll(x => x.P_Id.Equals(item.ID));
                        //构造Select选择查询
                        if (SqlFunc.IsNullOrEmpty(Select)) return;//如果没有选择字段，则跳过本次发送                        
                        List<SelectModel> selector = new();

                        List<OrderByModel> orderList = new();
                        List<GroupByModel> groupByList = new();
                        ObjectFuncModel objectFuncModel = new();


                        foreach (var field in Select)
                        {
                            SelectModel selectModel = new SelectModel();

                            if (!string.IsNullOrEmpty(field.ComputeMode))//判断是否是求和字段
                            {
                                switch (field.ComputeMode)
                                {
                                    case "求和": selectModel.FieldName = ObjectFuncModel.Create("AggregateSum", field.SelectField); break;
                                    case "平均": selectModel.FieldName = ObjectFuncModel.Create("AggregateAvg", field.SelectField); break;
                                    case "最大值": selectModel.FieldName = ObjectFuncModel.Create("AggregateMax", field.SelectField); break;
                                    case "最小值": selectModel.FieldName = ObjectFuncModel.Create("AggregateMin", field.SelectField); break;
                                    default:
                                        break;
                                }
                            }
                            else
                            {
                                selectModel.FieldName = field.SelectField;
                            }
                            selectModel.AsName = field.FieldAlias;//设置别名
                            selector.Add(selectModel);

                            if (!string.IsNullOrEmpty(field.FieldSort))
                            {
                                //构造排序条件
                                OrderByModel orderByModel = new OrderByModel();
                                orderByModel.FieldName = field.SelectField;

                                if (field.FieldSort == "倒序")
                                {
                                    orderByModel.OrderByType = OrderByType.Desc;
                                }
                                else
                                {
                                    orderByModel.OrderByType = OrderByType.Asc;
                                }
                                orderList.Add(orderByModel);
                            }

                            //添加分组字段
                            if (field.IsGroupBy.Equals("是"))
                            {
                                GroupByModel groupByModel = new GroupByModel();
                                groupByModel.FieldName = field.SelectField;
                                groupByList.Add(groupByModel);
                            }
                        }

                        #endregion

                        //构造分组
                        //方式1：多库兼容
                        //var groupList = GroupByModel.Create(new GroupByModel() { FieldName = "ID" }); //Sql: `id`
                        //var having = ObjectFuncModel.Create("AggregateSum",);

                        #region 执行SQL查询
                        object list;
                        if (item.SingleAndDouble.Equals("是"))
                        {
                            list = _repFilter.Context.Queryable<object>().AS(item.Link)
                                           .Where(conModels)
                                           .GroupBy(groupByList)
                                           .Select(selector)
                                           .OrderBy(orderList)
                                           .ToList();
                        }
                        else
                        {
                            list = _repFilter.Context.Queryable<object>().AS(item.Link)
                                          .Where(conModels)
                                          .GroupBy(groupByList)
                                          .Select(selector)
                                          .OrderBy(orderList)
                                          .First();
                        }
                        dict.Add(item.Name, list);
                        #endregion


                    }
                    catch (Exception e)
                    {
                        _businessDto.RealTimeMessage += $"时间{DateTime.Now}\r\n发送消息：{e.Message}\r\n\r\n";
                        return;
                    }
                });

                return dict;//返回结果

            }
            catch (Exception e)
            {
                //数据日志
                _businessDto.RealTimeMessage += $"时间{DateTime.Now}\r\n发送消息：{e.Message}\r\n\r\n";
                return new Dictionary<string, object>();
            }
        }

    }
}